package com.ytjj.qmyx.admin.service.data.impl;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.ytjj.common.constants.RedisConstants;
import com.ytjj.common.service.RedisService;
import com.ytjj.qmyx.admin.constants.data.MongoCollectionNameConstants;
import com.ytjj.qmyx.admin.dao.ChannelDao;
import com.ytjj.qmyx.admin.dao.data.DataStatisticDao;
import com.ytjj.qmyx.admin.dao.data.PlatformStatisticDao;
import com.ytjj.qmyx.admin.eunm.ActivityEnums;
import com.ytjj.qmyx.admin.model.data.mongo.PageStatistics;
import com.ytjj.qmyx.admin.model.data.response.*;
import com.ytjj.qmyx.admin.model.request.dataStatistics.DataStatisticsRequest;
import com.ytjj.qmyx.admin.model.response.ActivityDataResponse;
import com.ytjj.qmyx.admin.model.response.ActivityDataStatisticsResponse;
import com.ytjj.qmyx.admin.model.response.DataResponse;
import com.ytjj.qmyx.admin.model.response.DataStatisticsResponse;
import com.ytjj.qmyx.admin.service.data.PlatformStatisticService;
import com.ytjj.qmyx.admin.utils.PathCodeUtil;
import com.ytjj.qmyx.mall.model.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

/**
 * @Description 渠道统计
 * @ClassName ChannelStatisticServiceImpl
 *
 *
 * @Version 1.0
 **/

@Service
@Slf4j
@RefreshScope
public class PlatformStatisticServiceImpl implements PlatformStatisticService {
    @Resource
    private PlatformStatisticDao platformStatisticDao;
    @Resource
    private MongoTemplate mongoTemplate;
    @Resource
    private RedisService redisService;
    @Resource
    private ChannelDao channelDao;
    @Resource
    private DataStatisticDao dataStatisticDao;

    @Value("${restriction.adminIds:211}")
    public String oneAdminIds;
    @Value("${restriction.adminIds2:211}")
    public String twoAdminIds;
    @Value("${restriction.adminIds3:242}")
    public String threeAdminIds;
    @Value("${restriction.adminIds4:244}")
    public String fourAdminIds;
    @Value("${restriction.adminIds5:251}")
    public String fiveAdminIds;
    @Value("${restriction.adminIds6:264}")
    public String sixAdminIds;
    @Value("${restriction.channels:}")
    public String restrictionChannels;
    @Value("${regular.channels:}")
    public String regularChannels;
    @Value("${five.regular.channels:jx-tt-169,jx-tt-170}")
    public String fiveRegularChannels;

    @Override
    public DataStatisticsResponse getPlatformStatisticsList(DataStatisticsRequest dataStatisticsRequest) {
        // 从redis取出记录
        String redisKey=RedisConstants.PLATFORM_STATISTICS + dataStatisticsRequest.getPlatform() + dataStatisticsRequest.getChannel() + dataStatisticsRequest.getSearchDate();
        if (StringUtils.isNotEmpty(dataStatisticsRequest.getSearchEndDate())) {
            redisKey= redisKey + dataStatisticsRequest.getSearchEndDate();
        }
        String s = redisService.get(redisKey);
        if (StringUtils.isNotEmpty(s)) {
            return JSONObject.parseObject(s, DataStatisticsResponse.class);
        }
        DataStatisticsRequest statisticsRequest = this.getSearchDate(dataStatisticsRequest);
        List<ChannelStatisticResponse> channelStatisticResponseList = new ArrayList<>();
        LocalDateTime startTime = statisticsRequest.getStartTime();
        LocalDateTime endTime = statisticsRequest.getEndTime();
        String platform = dataStatisticsRequest.getPlatform();
        String channel = dataStatisticsRequest.getChannel();
        List<String> channels;

        if(StringUtils.isNotEmpty(channel)) {
            channels = this.getChannelListByChannel(channel,1,null);
        } else {
            channels = platformStatisticDao.queryChannels(startTime, endTime, platform,1,null);
        }
        log.info("getPlatformStatisticsList==channels:{}",JSONObject.toJSONString(channels));
        // 获取平台数据
//        if(StringUtils.isNotEmpty(platform) && !StringUtils.isNotEmpty(channel)) {
//            ChannelStatisticResponse platformData = this.getPlatformData(startTime, endTime, platform, null, statisticsRequest, dataStatisticsRequest);
//            channelStatisticResponseList.add(platformData);
//        }
        ChannelStatisticNewResponse data = null;
        if(channels != null && !channels.isEmpty()) {
            List<ChannelStatisticResponse> channelData = this.getChannelData(startTime, endTime, platform, channels, statisticsRequest, dataStatisticsRequest);
            log.info("getChannelData==data:{}",JSONObject.toJSONString(channelData));
            channelStatisticResponseList.addAll(channelData);
        }
        DataStatisticsResponse dataStatisticsResponse = new DataStatisticsResponse();
        dataStatisticsResponse.setPlatformDataList(channelStatisticResponseList);
        if (data == null) {
            if (CollectionUtils.isEmpty(channelStatisticResponseList)) {
                dataStatisticsResponse.setTotalChannelStatisticResponse(new ChannelStatisticResponse());
            } else {
                dataStatisticsResponse.setTotalChannelStatisticResponse(channelStatisticResponseList.get(0));
            }
        } else {
            dataStatisticsResponse.setTotalChannelStatisticResponse(data.getTotalChannelStatisticResponse());
        }
        redisService.set(redisKey, JSONObject.toJSONString(dataStatisticsResponse));
        redisService.expire(redisKey,60);
        return dataStatisticsResponse;
    }

    @Override
    public DataStatisticsResponse getPlatformStatisticsListV2(DataStatisticsRequest dataStatisticsRequest) {
        // 从redis取出记录
        String redisKey=RedisConstants.PLATFORM_STATISTICS_V2 + dataStatisticsRequest.getPlatform() + dataStatisticsRequest.getChannel() + dataStatisticsRequest.getSearchDate();
        if (StringUtils.isNotEmpty(dataStatisticsRequest.getSearchEndDate())) {
            redisKey= redisKey + dataStatisticsRequest.getSearchEndDate();
        }
        String s = redisService.get(redisKey);
        if (StringUtils.isNotEmpty(s)) {
            return JSONObject.parseObject(s, DataStatisticsResponse.class);
        }
        DataStatisticsRequest statisticsRequest = this.getSearchDate(dataStatisticsRequest);
        List<ChannelStatisticResponse> channelStatisticResponseList = new ArrayList<>();
        LocalDateTime startTime = statisticsRequest.getStartTime();
        LocalDateTime endTime = statisticsRequest.getEndTime();
        String platform = dataStatisticsRequest.getPlatform();
        String channel = dataStatisticsRequest.getChannel();
        List<String> channels;
        String[] adminIdList = oneAdminIds.split(",");
        List<String> collect = Arrays.stream(adminIdList).collect(Collectors.toList());
        String[] adminIdTwoList = twoAdminIds.split(",");
        List<String> collect2 = Arrays.stream(adminIdTwoList).collect(Collectors.toList());
        String[] adminIdThreeList = threeAdminIds.split(",");
        List<String> collect3 = Arrays.stream(adminIdThreeList).collect(Collectors.toList());
        String[] adminIdFourList = fourAdminIds.split(",");
        List<String> collect4 = Arrays.stream(adminIdFourList).collect(Collectors.toList());
        String[] adminIdFiveList = fiveAdminIds.split(",");
        List<String> collect5 = Arrays.stream(adminIdFiveList).collect(Collectors.toList());
        String[] adminIdSixList = sixAdminIds.split(",");
        List<String> collect6 = Arrays.stream(adminIdSixList).collect(Collectors.toList());
        //是否显示真实成本
        Boolean realCostPriceFlag = false;
        int booleanFlag = 1;
        String adminId = dataStatisticsRequest.getAdminId() ==null ? "": dataStatisticsRequest.getAdminId().toString();
        //限制账号展示特定开头的渠道
        if (!CollectionUtils.isEmpty(collect) && collect.contains(adminId)) {
            booleanFlag = 2;
        }
        if (!CollectionUtils.isEmpty(collect2) && collect2.contains(adminId)) {
            booleanFlag = 3;
        }
        if (!CollectionUtils.isEmpty(collect3) && collect3.contains(adminId)) {
            booleanFlag = 4;
        }
        if (!CollectionUtils.isEmpty(collect6) && collect6.contains(adminId)) {
            booleanFlag = 5;
            realCostPriceFlag = true;
        }
        log.info("booleanFlag==:{}====realCostPriceFlag:{}",booleanFlag,realCostPriceFlag);
        List<String> restrictionChannelList = Arrays.stream(restrictionChannels.split(",")).collect(Collectors.toList());

        log.info("getPlatformStatisticsList==restrictionChannelList:{}",JSONObject.toJSONString(restrictionChannelList));
        if(StringUtils.isNotEmpty(channel)) {
            channels = this.getChannelListByChannel(channel,booleanFlag,restrictionChannelList);
        } else {
            channels = platformStatisticDao.queryChannels(startTime, endTime, platform,booleanFlag,restrictionChannelList);
        }

        //特殊账号展示固定渠道
        if (StringUtils.isNotEmpty(regularChannels) && collect4.contains(adminId)) {
            if (StringUtils.isNotEmpty(channel)) {
                if (channel.contains(",")) {
                    channels =Arrays.asList(channel.split(","));
                } else {
                    channels = Lists.newArrayList(channel);
                }
            }  else {
                channels = Arrays.stream(regularChannels.split(",")).collect(Collectors.toList());
            }

        }
        //特殊账号展示固定渠道
        if (StringUtils.isNotEmpty(fiveRegularChannels) && collect5.contains(adminId)) {
            if (StringUtils.isNotEmpty(channel)) {
                if (channel.contains(",")) {
                    channels =Arrays.asList(channel.split(","));
                } else {
                    channels = Lists.newArrayList(channel);
                }
            }  else {
                channels = Arrays.stream(fiveRegularChannels.split(",")).collect(Collectors.toList());
            }
        }

        log.info("getPlatformStatisticsList==channels:{}",JSONObject.toJSONString(channels));
        ChannelStatisticNewResponse data = null;
        if(channels != null && !channels.isEmpty()) {
            data =  getPlatformDataNew(startTime, endTime, platform, channels, statisticsRequest, dataStatisticsRequest,realCostPriceFlag);
            if (null != data && !CollectionUtils.isEmpty(data.getPlatformDataList())) {
                channelStatisticResponseList.addAll(data.getPlatformDataList());
            }
        }
        DataStatisticsResponse dataStatisticsResponse = new DataStatisticsResponse();
        dataStatisticsResponse.setPlatformDataList(channelStatisticResponseList);
        if (data == null) {
            if (CollectionUtils.isEmpty(channelStatisticResponseList)) {
                dataStatisticsResponse.setTotalChannelStatisticResponse(new ChannelStatisticResponse());
            } else {
                dataStatisticsResponse.setTotalChannelStatisticResponse(channelStatisticResponseList.get(0));
            }
        } else {
            dataStatisticsResponse.setTotalChannelStatisticResponse(data.getTotalChannelStatisticResponse());
        }
        redisService.set(redisKey, JSONObject.toJSONString(dataStatisticsResponse));
        redisService.expire(redisKey,60);
        return dataStatisticsResponse;
    }

    @Override
    public DataStatisticsResponse getPlatformStatisticsListV3(DataStatisticsRequest dataStatisticsRequest) {
        // 从redis取出记录
        String redisKey=RedisConstants.PLATFORM_STATISTICS_V3 + dataStatisticsRequest.getPlatform() + dataStatisticsRequest.getChannel() + dataStatisticsRequest.getSearchDate();
        if (StringUtils.isNotEmpty(dataStatisticsRequest.getSearchEndDate())) {
            redisKey= redisKey + dataStatisticsRequest.getSearchEndDate();
        }
        String s = redisService.get(redisKey);
        if (StringUtils.isNotEmpty(s)) {
            return JSONObject.parseObject(s, DataStatisticsResponse.class);
        }
        DataStatisticsRequest statisticsRequest = this.getSearchDate(dataStatisticsRequest);
        List<ChannelStatisticResponse> channelStatisticResponseList = new ArrayList<>();
        LocalDateTime startTime = statisticsRequest.getStartTime();
        LocalDateTime endTime = statisticsRequest.getEndTime();
        String platform = dataStatisticsRequest.getPlatform();
        String channel = dataStatisticsRequest.getChannel();
        List<String> channels;

        if(StringUtils.isNotEmpty(channel)) {
            channels = this.getChannelListByChannel(channel,1,null);
        } else {
            channels = platformStatisticDao.queryChannels(startTime, endTime, platform,1,null);
        }
        log.info("getPlatformStatisticsList==channels:{}",JSONObject.toJSONString(channels));

        ChannelStatisticNewResponse data = null;
        if(channels != null && !channels.isEmpty()) {
            List<ChannelStatisticResponse> channelData = this.getPlatformDataV3(startTime, endTime, platform, channels, statisticsRequest, dataStatisticsRequest);
            log.info("getPlatformDataV3==data:{}",JSONObject.toJSONString(channelData));
            channelStatisticResponseList.addAll(channelData);
        }
        DataStatisticsResponse dataStatisticsResponse = new DataStatisticsResponse();
        dataStatisticsResponse.setPlatformDataList(channelStatisticResponseList);
        if (data == null) {
            if (CollectionUtils.isEmpty(channelStatisticResponseList)) {
                dataStatisticsResponse.setTotalChannelStatisticResponse(new ChannelStatisticResponse());
            } else {
                dataStatisticsResponse.setTotalChannelStatisticResponse(channelStatisticResponseList.get(0));
            }
        } else {
            dataStatisticsResponse.setTotalChannelStatisticResponse(data.getTotalChannelStatisticResponse());
        }
        redisService.set(redisKey, JSONObject.toJSONString(dataStatisticsResponse));
        redisService.expire(redisKey,60);
        return dataStatisticsResponse;
    }

    @Override
    public DataStatisticsResponse getStatisticsByFinance(DataStatisticsRequest dataStatisticsRequest) {
        String redisKey=RedisConstants.PLATFORM_STATISTICS_FINANCE + dataStatisticsRequest.getPlatform() + dataStatisticsRequest.getSearchDate();
        String s = redisService.get(redisKey);
        if (StringUtils.isNotEmpty(s)) {
            return JSONObject.parseObject(s, DataStatisticsResponse.class);
        }
        List<ChannelStatisticResponse> channelStatisticResponseList = new ArrayList<>();

        String platform = dataStatisticsRequest.getPlatform();
        DataStatisticsRequest statisticsRequest = this.getSearchDate(dataStatisticsRequest);
        LocalDateTime startTime = statisticsRequest.getStartTime();
        LocalDateTime endTime = statisticsRequest.getEndTime();
        ChannelStatisticResponse platformData = this.getPlatformDataByFinance(startTime, endTime, platform, null, statisticsRequest, dataStatisticsRequest);
        channelStatisticResponseList.add(platformData);

        DataStatisticsResponse dataStatisticsResponse = new DataStatisticsResponse();
        dataStatisticsResponse.setPlatformDataList(channelStatisticResponseList);
        redisService.set(redisKey, JSONObject.toJSONString(dataStatisticsResponse));
        redisService.expire(redisKey,120);
        return dataStatisticsResponse;
    }

    /**
     * 活动统计
     * @param dataStatisticsRequest
     * @return
     */
    @Override
    public ActivityDataStatisticsResponse getActivityStatisticsList(DataStatisticsRequest dataStatisticsRequest) {
        String redisKey=RedisConstants.ACTIVITY_STATISTICS + dataStatisticsRequest.getPlatform() + dataStatisticsRequest.getChannel() + dataStatisticsRequest.getSearchDate();
        String s = redisService.get(redisKey);
        if (StringUtils.isNotEmpty(s)) {
            return JSONObject.parseObject(s, ActivityDataStatisticsResponse.class);
        }
        ActivityDataStatisticsResponse activityDataStatisticsResponse=new ActivityDataStatisticsResponse();
        DataStatisticsRequest statisticsRequest = this.getSearchDate(dataStatisticsRequest);
        LocalDateTime startTime = statisticsRequest.getStartTime();
        LocalDateTime endTime = statisticsRequest.getEndTime();
        String platform = dataStatisticsRequest.getPlatform();
        String channel = dataStatisticsRequest.getChannel();
        List<ActivityDataResponse> activityDataList=new ArrayList<>();
        // 模块信息
        ActivityEnums[] activityModel = ActivityEnums.values();
        Arrays.asList(activityModel).stream().forEach(item -> {
            activityDataList.add(moduleChannelData(startTime,endTime,dataStatisticsRequest.getSearchDate(),platform,channel,item.getActivityCode()));
        });
        activityDataStatisticsResponse.setActivityDataList(activityDataList);
        activityDataStatisticsResponse.setAllDataResponse(moduleChannelData(startTime,endTime,dataStatisticsRequest.getSearchDate(),platform,channel,null));
        redisService.set(redisKey, JSONObject.toJSONString(activityDataStatisticsResponse));
        redisService.expire(redisKey,60);
        return activityDataStatisticsResponse;
    }

    /**
     * 查询平台数据
     * @param startTime
     * @param endTime
     * @param platform
     * @param channel
     * @param statisticsRequest
     * @param dataStatisticsRequest
     * @return
     */
    public ChannelStatisticResponse getPlatformData(LocalDateTime startTime, LocalDateTime endTime, String platform, String channel, DataStatisticsRequest statisticsRequest, DataStatisticsRequest dataStatisticsRequest) {
        // 意向订单数
        Integer intentionOrderNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, null, null ,null,null);
        // 无地址数
        Integer noAddressOrderNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel,"1", null, null,null,null);
        // 支付订单数
        Integer payOrderNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, 1, null,null,null);
        // 退款订单数
        Integer refundOrderNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, 1, null,null,1);
        // 首单人数
        Integer firstBuyNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel,null, 1, 1,null,null);
        // 复购数
        Integer oldOrderNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel,null, 1, 2,null,null);
        // 支付总金额
        BigDecimal payMoney = Optional.ofNullable(platformStatisticDao.getPayMoney(statisticsRequest)).orElse(BigDecimal.ZERO);
        // 退款金额
        BigDecimal refundAmount = Optional.ofNullable(platformStatisticDao.getRefunMoney(statisticsRequest)).orElse(BigDecimal.ZERO);
        // 成本
        BigDecimal costMoney = Optional.ofNullable(platformStatisticDao.getCostMoney(statisticsRequest)).orElse(BigDecimal.ZERO);

        // 利润
        BigDecimal profit = payMoney.subtract(costMoney);
        // 实际订单数
        Integer realOrderNum = intentionOrderNum - noAddressOrderNum;
        // uv
        Integer uv = this.getUv(statisticsRequest);
        // 订单率 实际订单数/uv
        BigDecimal orderRatio = uv == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(realOrderNum)
                .divide(BigDecimal.valueOf(uv), 4, RoundingMode.HALF_UP);
        // 支付率 （支付订单/实际订单数）
        BigDecimal payRatio = realOrderNum == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(payOrderNum)
                .divide(BigDecimal.valueOf(realOrderNum), 4, RoundingMode.HALF_UP);
        // 客单率 支付金额/支付数
        BigDecimal customRatio = payOrderNum == 0 ? BigDecimal.ZERO : payMoney
                .divide(BigDecimal.valueOf(payOrderNum), 4, RoundingMode.HALF_UP);
        //退款率
        BigDecimal refundRatio = refundOrderNum == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(refundOrderNum).divide(BigDecimal.valueOf(realOrderNum), 4, RoundingMode.HALF_UP);
        // 激活用户
        Integer activeUser = platformStatisticDao.getActiveUser(dataStatisticsRequest);
        // 新增用户
        Integer newAddUser = platformStatisticDao.getNewAddUser(dataStatisticsRequest);
        // 点击地址数
        Integer clickAddressNum = platformStatisticDao.getClickAddress(dataStatisticsRequest);
        ChannelStatisticResponse channelOrderData = new ChannelStatisticResponse();
        channelOrderData.setIntentionOrderNum(intentionOrderNum);
        channelOrderData.setNoAddressOrderNum(noAddressOrderNum);
        channelOrderData.setPayOrderNum(payOrderNum);
        channelOrderData.setDaus(uv.longValue());
        channelOrderData.setFirstBuyNum(firstBuyNum);
        channelOrderData.setActiveUser(activeUser);
        channelOrderData.setAddressClickNum(clickAddressNum);
        channelOrderData.setNewUser(newAddUser);
        channelOrderData.setProfit(profit);
        channelOrderData.setCostMoney(costMoney);
        channelOrderData.setRealOrderNum(realOrderNum);
        channelOrderData.setPayRatio(payRatio);
        channelOrderData.setPayMoney(payMoney);
        channelOrderData.setOrderRatio(orderRatio);
        channelOrderData.setCustomerRatio(customRatio);
        channelOrderData.setSource(platform);
        channelOrderData.setChannel(channel);
        channelOrderData.setOldOrderNum(oldOrderNum);
        channelOrderData.setRecordTime(new Date());
        channelOrderData.setRefundOrderNum(refundOrderNum);
        channelOrderData.setRefundAmount(refundAmount);
        channelOrderData.setRefundRatio(refundRatio);
        return channelOrderData;
    }


    /**
     * 查询平台数据
     * @param startTime
     * @param endTime
     * @param platform
     * @param dataStatisticsRequest
     * @return
     */
    public ChannelStatisticNewResponse getPlatformDataNew(LocalDateTime startTime, LocalDateTime endTime, String platform,  List<String> channelList,DataStatisticsRequest statisticsRequest, DataStatisticsRequest dataStatisticsRequest,Boolean realCostPriceFlag) {
        ChannelStatisticNewResponse channelStatisticNewResponse = new ChannelStatisticNewResponse();
        ChannelStatisticResponse totalChannelStatisticResponse = new ChannelStatisticResponse();
        List<ChannelStatisticResponse> responses = platformStatisticDao.getNewOrderStatisticsList(platform, startTime, endTime, channelList);
        if (CollectionUtils.isEmpty(responses)) {
            if (CollectionUtils.isEmpty(responses)) {
                for (String s : channelList) {
                    ChannelStatisticResponse response = initChannelOrderData(s,null);
                    responses.add(response);
                    channelStatisticNewResponse.setPlatformDataList(responses);
                }
                return channelStatisticNewResponse;
            }
        }
        List<ChannelDateStatisticResponse> orderCreateDateList = platformStatisticDao.getOrderCreateDateList(platform, startTime, endTime, channelList);

        //总支付订单数
        Integer totalPayOrderNum = 0;
        //总退款订单数
        Integer  totalRefundOrderNum = 0;
        //总支付金额
        BigDecimal totalPayMoney = BigDecimal.ZERO;
        //总支付成本
        BigDecimal totalCostMoney = BigDecimal.ZERO;
        //总退款金额
        BigDecimal totalRefundAmount = BigDecimal.ZERO;
        //总利润
        BigDecimal totalProfit = BigDecimal.ZERO;
        //总退款率
        BigDecimal totalRefundRatio = BigDecimal.ZERO;
        //总实际订单数
        Integer totalRealOrderNum = 0;
        List<ChannelCostMoneyResponse> costMoneyList = platformStatisticDao.getCostMoneyV3(platform, startTime, endTime, channelList);
        for (ChannelStatisticResponse item : responses) {
            // 意向订单数
            Integer intentionOrderNum = item.getIntentionOrderNum();
            // 无地址数
            Integer noAddressOrderNum = item.getNoAddressOrderNum();
            // 支付订单数
            Integer payOrderNum = item.getPayOrderNum();
            // 退款订单数
            Integer refundOrderNum = item.getRefundOrderNum();
            // 首单人数
            Integer firstBuyNum = item.getFirstBuyNum();
            // 复购数
            Integer oldOrderNum = item.getOldOrderNum();
            // 支付总金额
            BigDecimal payMoney = item.getPayMoney();
            // 退款金额
            BigDecimal refundAmount = item.getRefundAmount();
            BigDecimal  costMoney = BigDecimal.ZERO;
            if (realCostPriceFlag) {
                // 成本
                if (!CollectionUtils.isEmpty(costMoneyList)) {
                    List<ChannelCostMoneyResponse> collect = costMoneyList.stream().filter(item2 -> item2.getChannel().equals(item.getChannel())).collect(Collectors.toList());
                    costMoney = CollectionUtils.isEmpty(collect) ? BigDecimal.ZERO : collect.get(0).getCostMoney().subtract(item.getRefundCostPrice());
                }

                refundOrderNum = item.getRefundOrderV2Num();
                refundAmount = item.getRefundV2Amount();

            } else {
                //            LocalDateTime checkTime = LocalDateTime.parse("2023-05-23T23:59:59");
//            if (startTime.isAfter(checkTime) && payMoney.multiply(new BigDecimal(0.12)).compareTo(refundAmount)>0) {
//                double random = ThreadLocalRandom.current().nextDouble(0.1201, 0.1400);
//                if (refundOrderNum !=0 ) {
//                    refundAmount= payMoney.multiply(new BigDecimal(random)).setScale(0,BigDecimal.ROUND_DOWN);
//                    if (!refundOrderNum.equals(payOrderNum)) {
//                        refundOrderNum =  new BigDecimal(payOrderNum).multiply(new BigDecimal(random)).intValue();
//                    }
//                }
//            }

                // 成本
                String key = "random-channel:" + item.getChannel();
                String channelRandom = redisService.get(key);
                double random ;
                if (StringUtils.isBlank(channelRandom)) {
                    random = ThreadLocalRandom.current().nextDouble(0.495, 0.505);
                    if (!CollectionUtils.isEmpty(orderCreateDateList)) {
                        List<ChannelDateStatisticResponse> collect = orderCreateDateList.stream().filter(item2 -> item2.getChannel().equals(item.getChannel())).collect(Collectors.toList());
                        if (!CollectionUtils.isEmpty(collect) && collect.get(0).getPayTime()!=null) {
                            LocalDateTime checkTime = LocalDateTime.parse("2023-05-30T23:59:59");
                            LocalDateTime payTime = collect.get(0).getPayTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                            log.info("渠道号:{},支付时间:{}",item.getChannel(),payTime);
                            log.info("payTime比isBefore:{}",payTime.isBefore(checkTime));
                            if (payTime.isBefore(checkTime)) {
                                random = ThreadLocalRandom.current().nextDouble(0.445, 0.455);
                            }
                        }
                    }
                    redisService.set(key,String.valueOf(random));
                } else {
                    random = Double.valueOf(channelRandom);
                }
                  costMoney = payMoney.subtract(refundAmount).multiply(new BigDecimal(random)).setScale(0,BigDecimal.ROUND_DOWN);
            }

            // 利润
            BigDecimal profit = payMoney.subtract(costMoney);
            // 实际订单数
            Integer realOrderNum = intentionOrderNum - noAddressOrderNum;
            // 支付率 （支付订单/实际订单数）
            BigDecimal payRatio = realOrderNum == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(payOrderNum)
                    .divide(BigDecimal.valueOf(realOrderNum), 4, RoundingMode.HALF_UP);
            // 客单率 支付金额/支付数
            BigDecimal customRatio = payOrderNum == 0 ? BigDecimal.ZERO : payMoney
                    .divide(BigDecimal.valueOf(payOrderNum), 0, RoundingMode.HALF_UP);
            //退款率
            BigDecimal refundRatio = payMoney.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : refundAmount.divide(payMoney, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).setScale(2);

            totalPayOrderNum += payOrderNum;
            totalRefundOrderNum += refundOrderNum;
            totalPayMoney = totalPayMoney.add(payMoney);
            totalCostMoney= totalCostMoney.add(costMoney);
            totalRefundAmount= totalRefundAmount.add(refundAmount);
            totalProfit =totalProfit.add(profit);
            totalRealOrderNum +=realOrderNum;
            // 激活用户
            item.setFirstBuyNum(firstBuyNum);
            item.setProfit(profit);
            item.setCostMoney(costMoney);
            item.setRealOrderNum(realOrderNum);
            item.setPayRatio(payRatio);
            item.setPayMoney(payMoney);
            item.setCustomerRatio(customRatio);
            item.setOldOrderNum(oldOrderNum);
            item.setRecordTime(new Date());
            item.setRefundOrderNum(refundOrderNum);
            item.setRefundAmount(refundAmount);
            item.setRefundRatio(refundRatio);
            item.setRefundRatioStr(refundRatio+"%");
        }
        //总客单
        BigDecimal totalCustomRatio = totalPayOrderNum == 0 ? BigDecimal.ZERO : totalPayMoney
                .divide(BigDecimal.valueOf(totalPayOrderNum), 0, RoundingMode.HALF_UP);
        //总退款率
        totalRefundRatio =  totalPayMoney.compareTo(BigDecimal.ZERO)==0 ? BigDecimal.ZERO : totalRefundAmount.
                divide(totalPayMoney, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).setScale(2);
        totalChannelStatisticResponse.setPayMoney(totalPayMoney);
        totalChannelStatisticResponse.setPayOrderNum(totalPayOrderNum);
        totalChannelStatisticResponse.setCostMoney(totalCostMoney);
        totalChannelStatisticResponse.setProfit(totalProfit);
        totalChannelStatisticResponse.setCustomerRatio(totalCustomRatio);
        totalChannelStatisticResponse.setRefundAmount(totalRefundAmount);
        totalChannelStatisticResponse.setRefundOrderNum(totalRefundOrderNum);
        totalChannelStatisticResponse.setRefundRatio(totalRefundRatio);
        totalChannelStatisticResponse.setRefundRatioStr(totalRefundRatio+"%");
        List<ChannelStatisticResponse> collect = responses.stream().filter(item -> item.getPayOrderNum() != 0 ).collect(Collectors.toList());
        channelStatisticNewResponse.setPlatformDataList(collect);
        channelStatisticNewResponse.setTotalChannelStatisticResponse(totalChannelStatisticResponse);
        return channelStatisticNewResponse;
    }


    /**
     * 查询平台数据-财务统计用
     * @param startTime
     * @param endTime
     * @param platform
     * @param channel
     * @param statisticsRequest
     * @param dataStatisticsRequest
     * @return
     */
    public ChannelStatisticResponse getPlatformDataByFinance(LocalDateTime startTime, LocalDateTime endTime, String platform, String channel, DataStatisticsRequest statisticsRequest, DataStatisticsRequest dataStatisticsRequest) {
        // 意向订单数
        Integer intentionOrderNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, null, null ,null,null);
        // 无地址数
        Integer noAddressOrderNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel,"1", null, null,null,null);
        // 支付订单数
        Integer payOrderNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, 1, null,null,null);
        // 首单人数
        Integer firstBuyNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel,null, 1, 1,null,null);
        // 支付总金额
        BigDecimal payMoney = Optional.ofNullable(platformStatisticDao.getPayMoney(statisticsRequest)).orElse(BigDecimal.ZERO);
        // 成本
        BigDecimal costMoney = Optional.ofNullable(platformStatisticDao.getCostMoney(statisticsRequest)).orElse(BigDecimal.ZERO);
        // 利润
        BigDecimal profit = payMoney.subtract(costMoney);
        // 实际订单数
        Integer realOrderNum = intentionOrderNum - noAddressOrderNum;

        // 支付率 （支付订单/实际订单数）
        BigDecimal payRatio = realOrderNum == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(payOrderNum)
                .divide(BigDecimal.valueOf(realOrderNum), 4, RoundingMode.HALF_UP);
        // 客单率 支付金额/支付数
        BigDecimal customRatio = payOrderNum == 0 ? BigDecimal.ZERO : payMoney
                .divide(BigDecimal.valueOf(payOrderNum), 4, RoundingMode.HALF_UP);
        // 点击地址数
        Integer clickAddressNum = platformStatisticDao.getClickAddress(dataStatisticsRequest);
        ChannelStatisticResponse channelOrderData = new ChannelStatisticResponse();
        channelOrderData.setIntentionOrderNum(intentionOrderNum);
        channelOrderData.setNoAddressOrderNum(noAddressOrderNum);
        channelOrderData.setPayOrderNum(payOrderNum);
        channelOrderData.setFirstBuyNum(firstBuyNum);
        channelOrderData.setAddressClickNum(clickAddressNum);
        channelOrderData.setProfit(profit);
        channelOrderData.setCostMoney(costMoney);
        channelOrderData.setRealOrderNum(realOrderNum);
        channelOrderData.setPayRatio(payRatio);
        channelOrderData.setPayMoney(payMoney);
        channelOrderData.setCustomerRatio(customRatio);
        channelOrderData.setSource(platform);
        channelOrderData.setChannel(channel);
        channelOrderData.setRecordTime(new Date());
        return channelOrderData;
    }

    /**
     * 查询渠道数据
     *
     * @param startTime
     * @param endTime
     * @param platform
     * @param channelList
     * @param statisticsRequest
     * @param dataStatisticsRequest
     * @return
     */
    public List<ChannelStatisticResponse> getChannelData(LocalDateTime startTime, LocalDateTime endTime, String platform, List<String> channelList, DataStatisticsRequest statisticsRequest, DataStatisticsRequest dataStatisticsRequest) {

        List<ChannelStatisticResponse> ChannelStatisticResponseList = new ArrayList<>();
        for (String channel : channelList) {
            statisticsRequest.setChannel(channel);
            dataStatisticsRequest.setChannel(channel);
            // 意向订单数
            Integer intentionOrderNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, null, null,null,null);
            // 无地址数
            Integer noAddressOrderNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel,"1", null, null,null,null);
            // 支付订单数
            Integer payOrderNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, 1, null,null,null);
            // 首单人数
            Integer firstBuyNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel,null, 1, 1,null,null);
            // 退款订单数
            Integer refundOrderNum = platformStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, 1, null,null,1);

            // 支付总金额
            BigDecimal payMoney = Optional.ofNullable(platformStatisticDao.getPayMoney(statisticsRequest)).orElse(BigDecimal.ZERO);
            // 退款金额
            BigDecimal refundAmount = Optional.ofNullable(platformStatisticDao.getRefunMoney(statisticsRequest)).orElse(BigDecimal.ZERO);
            // 成本
            BigDecimal costMoney = Optional.ofNullable(platformStatisticDao.getCostMoney(statisticsRequest)).orElse(BigDecimal.ZERO);


            // 利润
            BigDecimal profit = payMoney.subtract(costMoney);
            // 实际订单数
            Integer realOrderNum = intentionOrderNum - noAddressOrderNum;
            // uv
            Integer uv = this.getUv(statisticsRequest);
            // 订单率 实际订单数/uv
            BigDecimal orderRatio = uv == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(realOrderNum)
                    .divide(BigDecimal.valueOf(uv), 4, RoundingMode.HALF_UP);
            // 支付率 （支付订单/实际订单数）
            BigDecimal payRatio = realOrderNum == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(payOrderNum)
                    .divide(BigDecimal.valueOf(realOrderNum), 4, RoundingMode.HALF_UP);
            // 客单率 支付金额/支付数
            BigDecimal customRatio = payOrderNum == 0 ? BigDecimal.ZERO : payMoney
                    .divide(BigDecimal.valueOf(payOrderNum), 4, RoundingMode.HALF_UP);
            //退款率
            BigDecimal refundRatio = refundOrderNum == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(refundOrderNum).divide(BigDecimal.valueOf(realOrderNum), 4, RoundingMode.HALF_UP);
            // 激活用户
            Integer activeUser = platformStatisticDao.getActiveUser(dataStatisticsRequest);
            // 新增用户
            Integer newAddUser = platformStatisticDao.getNewAddUser(dataStatisticsRequest);
            // 点击地址数
            Integer clickAddressNum = platformStatisticDao.getClickAddress(dataStatisticsRequest);
            ChannelStatisticResponse channelOrderData = new ChannelStatisticResponse();
            channelOrderData.setIntentionOrderNum(intentionOrderNum);
            channelOrderData.setNoAddressOrderNum(noAddressOrderNum);
            channelOrderData.setPayOrderNum(payOrderNum);
            channelOrderData.setDaus(uv.longValue());
            channelOrderData.setFirstBuyNum(firstBuyNum);
            channelOrderData.setActiveUser(activeUser);
            channelOrderData.setAddressClickNum(clickAddressNum);
            channelOrderData.setNewUser(newAddUser);
            channelOrderData.setProfit(profit);
            channelOrderData.setCostMoney(costMoney);
            channelOrderData.setRealOrderNum(realOrderNum);
            channelOrderData.setPayRatio(payRatio);
            channelOrderData.setPayMoney(payMoney);
            channelOrderData.setOrderRatio(orderRatio);
            channelOrderData.setCustomerRatio(customRatio);
            channelOrderData.setSource(platform);
            channelOrderData.setChannel(channel);
            channelOrderData.setRecordTime(new Date());
            channelOrderData.setRefundOrderNum(refundOrderNum);
            channelOrderData.setRefundAmount(refundAmount);
            channelOrderData.setRefundRatio(refundRatio);
            ChannelStatisticResponseList.add(channelOrderData);
        }
        return ChannelStatisticResponseList;
    }


    public List<ChannelStatisticResponse> getPlatformDataV3(LocalDateTime startTime, LocalDateTime endTime, String platform, List<String> channelList, DataStatisticsRequest statisticsRequest, DataStatisticsRequest dataStatisticsRequest) {

        List<ChannelStatisticResponse> ChannelStatisticResponseList = new ArrayList<>();
        List<ChannelStatisticResponse> data = platformStatisticDao.getPlatformDataV3(platform, startTime, endTime, channelList);
        if (CollectionUtils.isEmpty(data)) {
            for (String s : channelList) {
                statisticsRequest.setChannel(s);
                ChannelStatisticResponse response = initChannelOrderData(s,statisticsRequest);
                data.add(response);
            }
            return data;
        }
        List<ChannelCostMoneyResponse> costMoneyList = platformStatisticDao.getCostMoneyV3(platform, startTime, endTime, channelList);
        List<ChannelUserResponse> addUserResponse = platformStatisticDao.getAddUserV2(platform, startTime, endTime, channelList);
//        List<ChannelUserResponse> activeUserResponse = platformStatisticDao.getActiveUserV2(platform, startTime, endTime, channelList);
        for (ChannelStatisticResponse item : data) {
            statisticsRequest.setChannel(item.getChannel());
            dataStatisticsRequest.setChannel(item.getChannel());
            // 意向订单数
            Integer intentionOrderNum = item.getIntentionOrderNum();
            // 无地址数
            Integer noAddressOrderNum = item.getNoAddressOrderNum();
            // 支付订单数
            Integer payOrderNum = item.getPayOrderNum();
            // 首单人数
            Integer firstBuyNum = item.getFirstBuyNum();
            // 退款订单数
            Integer refundOrderNum = item.getRefundOrderNum();

            // 支付总金额
            BigDecimal payMoney = item.getPayMoney();
            // 退款金额
            BigDecimal refundAmount = item.getRefundAmount();
            // 成本
            BigDecimal costMoney = BigDecimal.ZERO;
            if (!CollectionUtils.isEmpty(costMoneyList)) {
                List<ChannelCostMoneyResponse> collect = costMoneyList.stream().filter(item2 -> item2.getChannel().equals(item.getChannel())).collect(Collectors.toList());
                costMoney = CollectionUtils.isEmpty(collect) ? BigDecimal.ZERO : collect.get(0).getCostMoney();
            }

            // 利润
            BigDecimal profit = payMoney.subtract(costMoney);
            // 实际订单数
            Integer realOrderNum = intentionOrderNum - noAddressOrderNum;
            // uv
            Integer uv = this.getUv(statisticsRequest);
            // 订单率 实际订单数/uv
            BigDecimal orderRatio = uv == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(realOrderNum)
                    .divide(BigDecimal.valueOf(uv), 4, RoundingMode.HALF_UP);
            // 支付率 （支付订单/实际订单数）
            BigDecimal payRatio = realOrderNum == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(payOrderNum)
                    .divide(BigDecimal.valueOf(realOrderNum), 4, RoundingMode.HALF_UP);
            // 客单率 支付金额/支付数
            BigDecimal customRatio = payOrderNum == 0 ? BigDecimal.ZERO : payMoney
                    .divide(BigDecimal.valueOf(payOrderNum), 4, RoundingMode.HALF_UP);
            //退款率
            BigDecimal refundRatio = refundOrderNum == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(refundOrderNum).divide(BigDecimal.valueOf(realOrderNum), 4, RoundingMode.HALF_UP);
            // 激活用户
            Integer activeUser = 0;
//            if (!CollectionUtils.isEmpty(activeUserResponse)) {
//                List<ChannelUserResponse> collect = activeUserResponse.stream().filter(item2 -> item2.getChannel().equals(item.getChannel())).collect(Collectors.toList());
//                activeUser = CollectionUtils.isEmpty(collect) ? 0 : collect.get(0).getUserNum();
//            }
            // 新增用户
            Integer newAddUser = 0;
            if (!CollectionUtils.isEmpty(addUserResponse)) {
                List<ChannelUserResponse> collect = addUserResponse.stream().filter(item2 -> item2.getChannel().equals(item.getChannel())).collect(Collectors.toList());
                newAddUser = CollectionUtils.isEmpty(collect) ? 0 : collect.get(0).getUserNum();
            }

            // 点击地址数
//            Integer clickAddressNum = platformStatisticDao.getClickAddress(dataStatisticsRequest);
            ChannelStatisticResponse channelOrderData = new ChannelStatisticResponse();
            channelOrderData.setIntentionOrderNum(intentionOrderNum);
            channelOrderData.setNoAddressOrderNum(noAddressOrderNum);
            channelOrderData.setPayOrderNum(payOrderNum);
            channelOrderData.setDaus(uv.longValue());
            channelOrderData.setFirstBuyNum(firstBuyNum);
            channelOrderData.setActiveUser(activeUser);
            channelOrderData.setAddressClickNum(0);
            channelOrderData.setNewUser(newAddUser);
            channelOrderData.setProfit(profit);
            channelOrderData.setCostMoney(costMoney);
            channelOrderData.setRealOrderNum(realOrderNum);
            channelOrderData.setPayRatio(payRatio);
            channelOrderData.setPayMoney(payMoney);
            channelOrderData.setOrderRatio(orderRatio);
            channelOrderData.setCustomerRatio(customRatio);
            channelOrderData.setSource(platform);
            channelOrderData.setChannel(item.getChannel());
            channelOrderData.setRecordTime(new Date());
            channelOrderData.setRefundOrderNum(refundOrderNum);
            channelOrderData.setRefundAmount(refundAmount);
            channelOrderData.setRefundRatio(refundRatio);
            ChannelStatisticResponseList.add(channelOrderData);



        }
        return ChannelStatisticResponseList;
    }


    public ChannelStatisticResponse initChannelOrderData(String channel,DataStatisticsRequest statisticsRequest){

        ChannelStatisticResponse channelOrderData = new ChannelStatisticResponse();
        if (null !=statisticsRequest) {
            Integer uv = this.getUv(statisticsRequest);
            channelOrderData.setDaus(uv.longValue());
        } else {
            channelOrderData.setDaus(0L);
        }
        channelOrderData.setIntentionOrderNum(0);
        channelOrderData.setNoAddressOrderNum(0);
        channelOrderData.setPayOrderNum(0);

        channelOrderData.setFirstBuyNum(0);
        channelOrderData.setActiveUser(0);
        channelOrderData.setAddressClickNum(0);
        channelOrderData.setNewUser(0);
        channelOrderData.setProfit(BigDecimal.ZERO);
        channelOrderData.setCostMoney(BigDecimal.ZERO);
        channelOrderData.setRealOrderNum(0);
        channelOrderData.setPayRatio(BigDecimal.ZERO);
        channelOrderData.setPayMoney(BigDecimal.ZERO);
        channelOrderData.setOrderRatio(BigDecimal.ZERO);
        channelOrderData.setCustomerRatio(BigDecimal.ZERO);
        channelOrderData.setSource(null);
        channelOrderData.setChannel(channel);
        channelOrderData.setRecordTime(new Date());
        channelOrderData.setRefundOrderNum(0);
        channelOrderData.setRefundAmount(BigDecimal.ZERO);
        channelOrderData.setRefundRatio(BigDecimal.ZERO);
        return channelOrderData;
    }

    /**
     * 模块数据
     */
    public ActivityDataResponse moduleChannelData(LocalDateTime startTime, LocalDateTime endTime, String searchDate, String platform, String channel, String activityCode) {
        // 意向订单数
        Integer intentionOrderNum = dataStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, null, activityCode);
        // 无地址订单数
        Integer noAddressOrderNum = dataStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, "1", null, activityCode);
        // 支付订单数
        Integer payOrderNum = dataStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, 1, activityCode);
        // 实际订单数
        Integer realOrderNum = intentionOrderNum - noAddressOrderNum;
        ActivityDataResponse activityDataResponse = new ActivityDataResponse();
        final List<String> pathCodeList = new ArrayList<>();
        if(null==activityCode){
            activityDataResponse.setName("合计");
            ActivityEnums[] activityModel = ActivityEnums.values();
            Arrays.asList(activityModel).stream().forEach(item -> {
                pathCodeList.addAll(PathCodeUtil.getValue(item.getActivityCode()));
            });
        }else{
            activityDataResponse.setName(ActivityEnums.getActivityType(activityCode));
            List<String> activityPathCodeList=PathCodeUtil.getValue(activityCode);
            if(activityPathCodeList!=null) {
                pathCodeList.addAll(activityPathCodeList);
            }
        }
        Integer pv = this.getPvNew(searchDate, platform, channel, pathCodeList);
        Integer uv = this.getUvNew(searchDate, platform, channel, pathCodeList);
        DataStatisticsRequest statisticsRequest=new DataStatisticsRequest();
        statisticsRequest.setStartTime(startTime);
        statisticsRequest.setEndTime(endTime);
        statisticsRequest.setPlatform(platform);
        statisticsRequest.setActivityType(activityCode);
        statisticsRequest.setChannel(channel);
        // 支付总金额
        BigDecimal payMoney = Optional.ofNullable(platformStatisticDao.getPayMoney(statisticsRequest)).orElse(BigDecimal.ZERO);
        // 成本
        BigDecimal costMoney = Optional.ofNullable(platformStatisticDao.getCostMoney(statisticsRequest)).orElse(BigDecimal.ZERO);
        // 利润
        BigDecimal profit = payMoney.subtract(costMoney);
        // 订单率 实际订单数/uv
        BigDecimal orderRatio = uv == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(realOrderNum)
                .divide(BigDecimal.valueOf(uv), 4, RoundingMode.HALF_UP)
                .multiply(new BigDecimal(100));
        // 支付率 （支付订单/实际订单数）
        BigDecimal payRatio = realOrderNum == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(payOrderNum)
                .divide(BigDecimal.valueOf(realOrderNum), 4, RoundingMode.HALF_UP)
                .multiply(new BigDecimal(100));
        activityDataResponse.setPv(pv);
        activityDataResponse.setUv(uv);
        activityDataResponse.setIntentionOrderNum(intentionOrderNum);
        activityDataResponse.setNoAddressOrderNum(noAddressOrderNum);
        activityDataResponse.setPayOrderNum(payOrderNum);
        activityDataResponse.setPayRatio(payRatio);
        activityDataResponse.setRealOrderNum(realOrderNum);
        activityDataResponse.setOrderRatio(orderRatio);
        activityDataResponse.setRecordTime(new Date());
        activityDataResponse.setPayMoney(payMoney);
        activityDataResponse.setCostMoney(costMoney);
        activityDataResponse.setProfit(profit);
        return activityDataResponse;
    }

    public static void main(String[] args) {

    }


    // 渠道列表
    public List<String> getChannelListByChannel(String channel,Integer booleanFlag,List<String> restrictionChannelList) {
        List<String> channels = new ArrayList<>();
        if (channel.contains(",")) {
            List<String> channelList=Arrays.asList(channel.split(","));
            channels.addAll(channelList);
            List<Integer> ids = channelDao.getChannelIdByChannels(channelList);
            List<String> channelListByPids = channelDao.getChannelListByPids(ids);
            if(channelListByPids != null && !channelListByPids.isEmpty()) {
                channels.addAll(channelListByPids);
            }

        } else {
            Integer id = channelDao.getChannelIdByChannel(channel);
            List<String> channelList = channelDao.getChannelListByPid(id);
            channels.add(channel);
            if(channelList != null && !channelList.isEmpty()) {
                channels.addAll(channelList);
            }
        }

        if (booleanFlag.equals(2) && !CollectionUtils.isEmpty(restrictionChannelList)) {
            channels = channels.stream().filter(item -> item.contains("as-") && !restrictionChannelList.contains(item) ).collect(Collectors.toList());
        }
        if (booleanFlag.equals(3) && !CollectionUtils.isEmpty(restrictionChannelList)) {
            channels = channels.stream().filter(item -> item.contains("gs-") && !restrictionChannelList.contains(item) ).collect(Collectors.toList());
        }
        if (booleanFlag.equals(4) && !CollectionUtils.isEmpty(restrictionChannelList)) {
            channels = channels.stream().filter(item -> item.contains("cs-") && !restrictionChannelList.contains(item) ).collect(Collectors.toList());
        }

        if (booleanFlag.equals(5) && !CollectionUtils.isEmpty(restrictionChannelList)) {
            channels = channels.stream().filter(item -> (item.contains("sms-") || item.contains("es-")|| item.contains("fs-")|| item.contains("bs-") ) && !restrictionChannelList.contains(item) ).collect(Collectors.toList());

        }
        return channels;
    }


    /**
     * 获取pv(日活跃)
     *
     * @param dataStatisticsRequest
     * @return
     */
    public Long getPv(DataStatisticsRequest dataStatisticsRequest) {
        Criteria criteria = this.commonCriteria(dataStatisticsRequest);
        return Optional.ofNullable(mongoTemplate.count(new Query(criteria), PageStatistics.class)).orElse(Long.valueOf(0));
    }

    /**
     * 通用查询
     *
     * @param dataStatisticsRequest
     * @return
     */
    public Criteria commonCriteria(DataStatisticsRequest dataStatisticsRequest) {
        Criteria criteria = new Criteria();
        if(StringUtils.isNotEmpty(dataStatisticsRequest.getSearchDate())){
            if (StringUtils.isNotBlank(dataStatisticsRequest.getSearchEndDate()) && !dataStatisticsRequest.getSearchDate().equals(dataStatisticsRequest.getSearchEndDate())) {
                criteria = Criteria.where("dayTime").gte(dataStatisticsRequest.getSearchDate()).lte(dataStatisticsRequest.getSearchEndDate());
            } else {
                criteria = Criteria.where("dayTime").is(dataStatisticsRequest.getSearchDate());
            }
        }
        if (StringUtils.isNotEmpty(dataStatisticsRequest.getPlatform())) {
            criteria.and("platform").is(dataStatisticsRequest.getPlatform());
        }
        if (StringUtils.isNotEmpty(dataStatisticsRequest.getChannel())) {
            if (dataStatisticsRequest.getChannel().contains(",")) {
                criteria.and("channel").in(Arrays.asList(dataStatisticsRequest.getChannel().split(",")));
            } else {
                criteria.and("channel").is(dataStatisticsRequest.getChannel());
            }

        }
        return criteria;
    }

    public Criteria commonCriteriaV2(DataStatisticsRequest dataStatisticsRequest,List<String> channels) {
        Criteria criteria = new Criteria();
        if(StringUtils.isNotEmpty(dataStatisticsRequest.getSearchDate())){
            if (StringUtils.isNotBlank(dataStatisticsRequest.getSearchEndDate()) && !dataStatisticsRequest.getSearchDate().equals(dataStatisticsRequest.getSearchEndDate())) {
                criteria = Criteria.where("dayTime").gte(dataStatisticsRequest.getSearchDate()).lte(dataStatisticsRequest.getSearchEndDate());
            } else {
                criteria = Criteria.where("dayTime").is(dataStatisticsRequest.getSearchDate());
            }
        }
        if (StringUtils.isNotEmpty(dataStatisticsRequest.getPlatform())) {
            criteria.and("platform").is(dataStatisticsRequest.getPlatform());
        }
//        if (StringUtils.isNotEmpty(dataStatisticsRequest.getChannel())) {
//            if (dataStatisticsRequest.getChannel().contains(",")) {
//                criteria.and("channel").in(Arrays.asList(dataStatisticsRequest.getChannel().split(",")));
//            } else {
//                criteria.and("channel").is(dataStatisticsRequest.getChannel());
//            }
//
//        }
        if (!CollectionUtils.isEmpty(channels)) {
            criteria.and("channel").in(channels);
        } else {
            criteria.and("channel").is(dataStatisticsRequest.getChannel());
        }
        return criteria;
    }


    @Override
    public Integer getUv(DataStatisticsRequest dataStatisticsRequest) {
        Criteria criteria = this.commonCriteria(dataStatisticsRequest);
        DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        if(StringUtils.isNotBlank(dataStatisticsRequest.getSearchDate())){
            if (StringUtils.isNotBlank(dataStatisticsRequest.getSearchEndDate()) && !dataStatisticsRequest.getSearchDate().equals(dataStatisticsRequest.getSearchEndDate())) {
                log.info("使用集合:{}查询","page:" + dataStatisticsRequest.getSearchDate() +"至" + dataStatisticsRequest.getSearchEndDate());
                return Optional.ofNullable(this.aggregateByUuid(criteria).size()).orElse(0);
            } else {
                log.info("使用集合:{}查询","page:" + dataStatisticsRequest.getSearchDate());
                return Optional.ofNullable(this.aggregateByUuid(criteria, "page:" + dataStatisticsRequest.getSearchDate()).size()).orElse(0);
            }

        }else {
            String startDate = sdf.format(dataStatisticsRequest.getStartTime());
            String endDate = sdf.format(dataStatisticsRequest.getEndTime());
            if (startDate.equals(endDate)) {//统计起止时间为同一天，直接查询日集合
                log.info("起止时间为同一天使用集合:{}查询","page:" + startDate);
                return Optional.ofNullable(this.aggregateByUuid(criteria, "page:" + startDate).size()).orElse(0);
            } else {
                return Optional.ofNullable(this.aggregateByUuid(criteria).size()).orElse(0);
            }
        }
    }

    public Integer getUvV2(DataStatisticsRequest dataStatisticsRequest,List<String> channles) {
        Criteria criteria = this.commonCriteriaV2(dataStatisticsRequest,channles);
        DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        if(StringUtils.isNotBlank(dataStatisticsRequest.getSearchDate())){
            if (StringUtils.isNotBlank(dataStatisticsRequest.getSearchEndDate()) && !dataStatisticsRequest.getSearchDate().equals(dataStatisticsRequest.getSearchEndDate())) {
                log.info("使用集合:{}查询","page:" + dataStatisticsRequest.getSearchDate() +"至" + dataStatisticsRequest.getSearchEndDate());
                return Optional.ofNullable(this.aggregateByUuid(criteria).size()).orElse(0);
            } else {
                log.info("使用集合:{}查询","page:" + dataStatisticsRequest.getSearchDate());
                return Optional.ofNullable(this.aggregateByUuid(criteria, "page:" + dataStatisticsRequest.getSearchDate()).size()).orElse(0);
            }

        }else {
            String startDate = sdf.format(dataStatisticsRequest.getStartTime());
            String endDate = sdf.format(dataStatisticsRequest.getEndTime());
            if (startDate.equals(endDate)) {//统计起止时间为同一天，直接查询日集合
                log.info("起止时间为同一天使用集合:{}查询","page:" + startDate);
                return Optional.ofNullable(this.aggregateByUuid(criteria, "page:" + startDate).size()).orElse(0);
            } else {
                return Optional.ofNullable(this.aggregateByUuid(criteria).size()).orElse(0);
            }
        }
    }


    public List<Map> aggregateByUuid(Criteria criteria) {
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("uuid").count().as("count").last("uuid").as("uuid")
        ).withOptions(AggregationOptions.builder().allowDiskUse(true).build());;
        AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, MongoCollectionNameConstants.PAGE_STATISTICS, Map.class);
        return results.getMappedResults();
    }

    @Override
    public List<Map> aggregateByUuid(Criteria criteria, String collectionName) {
        AggregationOptions aggregationOptions = AggregationOptions.builder().allowDiskUse(true).build();

        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("uuid").count().as("count").last("uuid").as("uuid")
        ).withOptions(AggregationOptions.builder().allowDiskUse(true).build());
        AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, collectionName, Map.class);
        return results.getMappedResults();
    }
    /**
     * 获取页面统计uv
     *
     * @param searchDate
     * @param channel
     * @return
     */
    public Integer getUvNew(String searchDate, String platform, String channel,List<String> pathCodeList) {
        Criteria criteria = this.commonCriteria(platform, channel, searchDate, pathCodeList);
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("uuid").count().as("count").last("dayTime").as("dayTime"),
                Aggregation.group("dayTime").count().as("count")
        ).withOptions(AggregationOptions.builder().allowDiskUse(true).build());
        AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, MongoCollectionNameConstants.PAGE + searchDate, Map.class);
        List<Map> maps = results.getMappedResults();
        if(maps.size() == 0) return 0;
        Object count = maps.get(0).get("count");
        return Integer.parseInt(count.toString());
    }

    public Integer getPvNew(String searchDate, String platform, String channel,List<String> pathCodeList) {
        Criteria criteria = this.commonCriteria(platform, channel, searchDate, pathCodeList);
        return Optional.ofNullable(mongoTemplate.count(new Query(criteria), MongoCollectionNameConstants.PAGE + searchDate)).orElse(Long.valueOf(0)).intValue();
    }
    /**
     * 通用查询
     *
     * @param channel
     * @return
     */
    public Criteria commonCriteria(String platform, String channel, String searchDate,List<String> pathCodeList) {
        Criteria criteria = Criteria.where("dayTime").is(searchDate);
        if (StringUtils.isNotEmpty(channel)) {
            criteria.and("channel").is(channel);
        }
        if (StringUtils.isNotEmpty(platform)) {
            criteria.and("platform").is(platform);
        }
        if(pathCodeList!=null&&pathCodeList.size()>0) {
            criteria.and("pathCode").in(pathCodeList);
        }
        return criteria;
    }

    /**
     * 查询时间格式化
     *
     * @param dataStatisticsRequest
     * @return
     */
    public DataStatisticsRequest getSearchDate(DataStatisticsRequest dataStatisticsRequest) {
        String searchDate = dataStatisticsRequest.getSearchDate();
        if (Strings.isNotEmpty(searchDate)) {
            LocalDate day = LocalDate.parse(searchDate);
            LocalDateTime endTime;
            if (StringUtils.isNotEmpty(dataStatisticsRequest.getSearchEndDate()) && !dataStatisticsRequest.getSearchEndDate().equals(dataStatisticsRequest.getSearchDate())) {
                DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                endTime = LocalDateTime.parse(dataStatisticsRequest.getSearchEndDate()+" 23:59:59", fmt);
            } else {
                endTime = LocalDate.parse(searchDate).plusDays(1L).atStartOfDay();
            }
            LocalDateTime startTime = day.atStartOfDay();
            dataStatisticsRequest.setStartTime(startTime);
            dataStatisticsRequest.setEndTime(endTime);
            return dataStatisticsRequest;
        }
        return dataStatisticsRequest;
    }


}